#include "door_common.h"
#include "gkt_door.h"

#if defined(GKT_CONFIG_DOOR_LOCK_ENABLE) && GKT_CONFIG_DOOR_LOCK_ENABLE \
	&& (!defined(GKT_CONFIG_BACKBOARD_ENABLE) || !GKT_CONFIG_BACKBOARD_ENABLE) \
	&& (!defined(GKT_CONFIG_DOOR_LOCK_AUTOMATIC) || !GKT_CONFIG_DOOR_LOCK_AUTOMATIC)

static __RETMEM_USR gkt_door_lock_st_e s_door_lock_status;

typedef struct _door_lock {
	int	init_ok;
	gkt_soft_timer_t	timer_id;
	int	timer_start;
	uint32_t	motor_rotate_time_ms;
	gkt_door_lock_motor_rotate_direction_e	motor_rotate_direction;
} door_lock_s;
static door_lock_s s_door_lock;

static int door_lock_set_motor_rotate_stop_timer(void)
{
	int retval;

	retval = gkt_soft_timer_start(s_door_lock.timer_id, 
					s_door_lock.motor_rotate_time_ms);
	if (GKT_SUCCESS == retval)
		s_door_lock.timer_start = 1;
	else
		gkt_error("door_lock: start motor rotate stop timer failed %d\n", retval);

	return retval;
}

static void door_lock_motor_rotate_stop_timer_callback(void *params)
{
	gkt_trace("door_lock_timer_callback :s_door_lock_status = %d\n", s_door_lock_status);

	s_door_lock.timer_start = 0;
	if (GKT_DOOR_LOCK_ST_OPENING == s_door_lock_status) {
		s_door_lock_status = GKT_DOOR_LOCK_ST_OPENED;
		door_lock_motor_rotate_stop();
		door_inner_notify(GKT_DOOR_NOTIFY_LOCK_STATUS, GKT_DOOR_LOCK_ST_OPENED);
	}
	else if (GKT_DOOR_LOCK_ST_CLOSING == s_door_lock_status) {
		s_door_lock_status = GKT_DOOR_LOCK_ST_CLOSED;
		door_lock_motor_rotate_stop();
		door_inner_notify(GKT_DOOR_NOTIFY_LOCK_STATUS, GKT_DOOR_LOCK_ST_CLOSED);
	}
}

static void door_lock_motor_start_rotation(int direction)
{
	// TODO:
	if (GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_FORWARD == direction) {
		door_lock_motor_rotate_forward();
	}
	else {
		door_lock_motor_rotate_reverse();
	}
}
uint32_t gkt_door_lock_get_status(void)
{
	return s_door_lock_status;
}

int gkt_door_lock_set_motor_rotate_direction(
				gkt_door_lock_motor_rotate_direction_e direction)
{
	gkt_trace("door_lock: motor_rotate_direction (%u -> %u)\n",
		s_door_lock.motor_rotate_direction, direction);

	if (direction < GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_MAX) {
		s_door_lock.motor_rotate_direction = direction;
		return GKT_SUCCESS;
	}

	return GKT_EPARAM;
}

uint32_t gkt_door_lock_get_motor_rotate_time(gkt_door_lock_motor_rotate_time_e type)
{
	gkt_unused(type);
	return s_door_lock.motor_rotate_time_ms;
}

int gkt_door_lock_set_motor_rotate_time(gkt_door_lock_motor_rotate_time_e type, 
				uint32_t time_ms)
{
	gkt_trace("door_lock: motor_rotate_time (%u -> %u)\n",
		s_door_lock.motor_rotate_time_ms, time_ms);

	if (GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_CLOSE ==  type)
	{
		if ((time_ms >= GKT_DOOR_LOCK_MOTOR_ROTATE_MINTIME_MS)
		&& (time_ms <= GKT_DOOR_LOCK_MOTOR_ROTATE_MAXTIME_MS))
		{
			s_door_lock.motor_rotate_time_ms = time_ms;
			return GKT_SUCCESS;
		}
	}
	return GKT_EPARAM;
}

int gkt_door_lock_open(void)
{
	int retval;

	if (!s_door_lock.init_ok)
		return GKT_ENOTINIT;

	gkt_trace("gkt_door_lock_open enter direction=%d, state=%d\n",
			s_door_lock.motor_rotate_direction, s_door_lock_status);

	if ((GKT_DOOR_LOCK_ST_CLOSED == s_door_lock_status)
		|| (GKT_DOOR_LOCK_ST_MAX == s_door_lock_status))
	{
		door_lock_motor_start_rotation(s_door_lock.motor_rotate_direction);

		retval = door_lock_set_motor_rotate_stop_timer();
		if (GKT_SUCCESS == retval) {
			s_door_lock_status = GKT_DOOR_LOCK_ST_OPENING;
			retval = GKT_EINPROCESS;
		}
		else {
			s_door_lock_status = GKT_DOOR_LOCK_ST_MAX;
			door_lock_motor_rotate_stop();
		}
	}
	else if (GKT_DOOR_LOCK_ST_OPENING == s_door_lock_status)
		retval = GKT_EINPROCESS;
	else if (GKT_DOOR_LOCK_ST_OPENED == s_door_lock_status)
		retval = GKT_SUCCESS;
	else
		retval = GKT_EPERMIT;

	return retval;
}

int gkt_door_lock_close(int double_close)
{
	gkt_unused(double_close);

	int retval;

	gkt_trace("gkt_door_lock_close enter direction=%d, state=%d\n",
		s_door_lock.motor_rotate_direction, s_door_lock_status);

	if (GKT_DOOR_LOCK_ST_OPENED == s_door_lock_status
		|| (GKT_DOOR_LOCK_ST_MAX == s_door_lock_status))
	{
		/* 1. start motor open rotation */
		if (s_door_lock.motor_rotate_direction == GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_FORWARD)
			door_lock_motor_start_rotation(GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_REVERSE);
		else
			door_lock_motor_start_rotation(GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_FORWARD);
		
		/* 2. start the timer */
		retval = door_lock_set_motor_rotate_stop_timer();
		if (GKT_SUCCESS == retval) {
			s_door_lock_status = GKT_DOOR_LOCK_ST_CLOSING;
			retval = GKT_EINPROCESS;
		}
		else {
			s_door_lock_status = GKT_DOOR_LOCK_ST_MAX;
			door_lock_motor_rotate_stop();
		}
	}
	else if (GKT_DOOR_LOCK_ST_CLOSING == s_door_lock_status) {
		retval = GKT_EINPROCESS;
	}
	else if (GKT_DOOR_LOCK_ST_CLOSED == s_door_lock_status) {
		retval = GKT_SUCCESS;
	}
	else
		retval = GKT_EPERMIT;

	return retval;
}

void gkt_door_lock_reset(void)
{
	if (s_door_lock.init_ok) {
		if (s_door_lock.timer_start) {
			s_door_lock.timer_start = 0;
			gkt_soft_timer_stop(s_door_lock.timer_id);
		}

		door_lock_motor_reset();
	}
}

uint32_t gkt_door_lock_get_timeout(gkt_door_lock_op_e op)
{
	gkt_unused(op);
	return s_door_lock.motor_rotate_time_ms;
}

void gkt_door_lock_standby(void)
{
	uint32_t value;
	
	G_BPK_ReadKey(&value, 1, GKT_RETMEM_DOOR_RELATE);
	value &= 0xFFFF00FF;
	value |= ((uint8_t)s_door_lock_status << 8);
	G_BPK_WriteKey(&value, 1, GKT_RETMEM_DOOR_RELATE);
	door_lock_motor_standby();
}

/************************************************************
* BPK Key:A total of 32 Uint32_t 
*		  uint32_t [0]:description:gkt_retmem.h
*         uint32_t [1]:			   
*			   Byte[0]:door tamper used 
					--io1  :door tamper detect level
*			   		--io1~2:door tamper gpio io number
*              Byte[1]:door lock used
					Record door lock status		 
************************************************************/
int door_lock_init(void)
{
	int retval;
	uint32_t value;
	
	if (GKT_SYSTEM_RESET_WAKEUP != g_system_info.reset_mode) {
		s_door_lock_status = GKT_DOOR_LOCK_ST_MAX;
		G_BPK_ReadKey(&value, 1, GKT_RETMEM_DOOR_RELATE);
		value &= 0xFFFF00FF;
		value |= (GKT_DOOR_LOCK_ST_MAX << 8);
		G_BPK_WriteKey(&value, 1, GKT_RETMEM_DOOR_RELATE);
	}
	else {
		G_BPK_ReadKey(&value, 1, GKT_RETMEM_DOOR_RELATE);
		s_door_lock_status = (value >> 8) & 0xff;
	}

	s_door_lock.init_ok = 0;
	s_door_lock.motor_rotate_time_ms = GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_MS;
	s_door_lock.motor_rotate_direction = GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION;
	s_door_lock.timer_start = 0;
	s_door_lock.timer_id = gkt_soft_timer_create(GKT_SOFT_TIMER_ONCE, 
						door_lock_motor_rotate_stop_timer_callback, NULL);
	if (!s_door_lock.timer_id) {
		gkt_error("door_lock: create soft timer failed!\n");
		return GKT_ECREATE;
	}

	retval = door_lock_motor_init();
	if (GKT_SUCCESS == retval)
		s_door_lock.init_ok = 1;

	return retval;
}

#endif

